﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinQtoObjectEX
{
    class Program
    {
        #region khoi tao du lieu
        // Datasource
        static List<Contact> contacts = Contact.SampleData();
        static List<CallLog> callogs = CallLog.SampleData();
        #endregion
        #region vidu truy van
        // return a list of formated strings based on data from a query over a collection of Contact record
        public static void ex1()
        {

            var q = from c in contacts
                    where c.DateOfBirth.AddYears(50) > DateTime.Now
                    orderby c.DateOfBirth descending
                    select string.Format("Ho van ten: {0} {1} - b.{2}", c.FirstName, c.LastName, c.DateOfBirth.ToString("dd-MMM-yyyy"));

            foreach (string s in q)
            {
                Console.WriteLine(s);
            }
        }

        //Query group Contact record into sub-collection based on their state
        public static void ex2()
        {
            var q2 = from c in contacts
                     group c by c.State;
            foreach (var queck in q2)
            {
                Console.WriteLine(queck.Count(st => st.State == "WA"));
                Console.WriteLine("State: " + queck.Key);
                foreach (var quack in queck)
                {
                    Console.WriteLine(quack.State + " " + quack.LastName);
                }
            }
        }
        // Join two collections : Contact and Callog by phone number.
        public static void ex3()
        {
            var joinCC = from contact in contacts
                         join callog in callogs on contact.Phone equals callog.Number
                         select new
                         {
                             callog.When,
                             contact.FirstName,
                             contact.LastName,
                             callog.Duration,
                             contact.Phone
                         };
            foreach (var c in joinCC)
            {
                Console.WriteLine("{0} - {1} {2} ({3})min == {4}", c.When.ToString("ddMMM HH:m"), c.FirstName, c.LastName, c.Duration, c.Phone);
            }

        }
        //incoming call log summary show filter, oder, join and select aggregate
        public static void ex4()
        {
            var joinoderfilterCC = from call in callogs
                                   where call.Incoming == true
                                   group call by call.Number into g
                                   join contact in contacts on g.Key equals contact.Phone
                                   orderby contact.FirstName, contact.LastName
                                   select new
                                   {
                                       Ho = contact.FirstName,
                                       Ten = contact.LastName,
                                       Dem = g.Count(),
                                       Avg = g.Average(c => c.Duration),
                                       Total = g.Sum(c => c.Duration)
                                   };
            foreach (var jofCC in joinoderfilterCC)
            {
                Console.WriteLine("{0}  {1}  - Calls: {2}, Time: {3}mins, Avg: {4}", jofCC.Ho, jofCC.Ten, jofCC.Dem, jofCC.Total, Math.Round(jofCC.Avg, 2));
            }
        }
        // using : let
        public static void ex5()
        {
            int[] source = new int[] { 1, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7 };
            var exlet = from s in source
                        let vinh = source.Average()
                        select Math.Pow((s - vinh), 2);
            foreach (var chan in exlet)
            {
                Console.WriteLine(chan);
            }


        }
        // into
        public static void ex6()
        {
            int[] source = new int[] { 1, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7 };
            //var exinto = from s in source
            //             group s by s into groups
            //             select new
            //             {
            //                 Key = groups.Key,
            //                 Count = groups.Count()
            //             };

            var exinto = from s in source
                         group s by s into groups
                         where groups.Count() == 5
                         let trungbinh = groups.Average()
                         select new { GT = trungbinh / 2 };
            foreach (var thich in exinto)
            {
                Console.WriteLine(thich.GT);
            }

        }
        // Style query
        public static void ex7()
        {
            // Style query option : 
            // Extension method 
            // query expression syntax.
            //Ex: Query get all contact in the state of "WA" ordered by lastname and  then first name using  extension method query syntax
            var exEM = contacts.Where(c => c.State == "WA").OrderBy(c => c.LastName.Length).ThenBy(c => c.FirstName);
            foreach (var yeu in exEM)
            {
                Console.WriteLine(yeu.FirstName);
            }
            // query expression syntax: 
            var exEM1 = from contact in contacts
                        where contact.State == "WA"
                        orderby contact.FirstName, contact.LastName
                        select contact;
        }
        //join extension method query
        public static void ex8()
        {
            var exJoins = callogs.Join(contacts, call => call.Number, contact => contact.Phone,
               (call, contact) => new
               {
                   contact.FirstName,
                   contact.LastName,
                   call.When,
                   call.Duration
               }).OrderByDescending(call => call.When).Take(5);
            foreach (var call in exJoins)
                Console.WriteLine("{0} - {1} {2} ({3}min)",
                call.When.ToString("ddMMM HH:m"),
                call.FirstName, call.LastName, call.Duration);
        }
        // join query expression
        public static void ex9()
        {
            var exJoins1 = (from call in callogs
                            join contact in contacts on call.Number equals contact.Phone
                            orderby call.When descending
                            select new { contact.FirstName, contact.LastName, call.When, call.Duration }).Take(5);

            foreach (var call in exJoins1)
                Console.WriteLine("{0} - {1} {2} ({3}min)",
                call.When.ToString("ddMMM HH:m"),
                call.FirstName, call.LastName, call.Duration);
        }

        // select many
        public static void ex10()
        {
            string[] mangstring = new string[] {
                "nguyen van vinh","yeu duong thi xuan thuy","hoang mai thao","yeu nguyen van vinh"
            };
            // option 1 : use select clause 
            IEnumerable<string[]> option1 = mangstring.Select(chuoitrongmangstring => chuoitrongmangstring.Split(' '));
            Console.WriteLine("Count option1 : {0}", option1.Count());
            Console.WriteLine("----------");
            foreach(var mang in option1)
            {
                Console.WriteLine("Mang hold {0} elements", mang.Length);
                foreach(string s in mang)
                {
                    Console.WriteLine(s);
                }
            }
            // -> option2 : use SelectMany 
            Console.WriteLine("-----------OPtion2");
            IEnumerable<string> option2 = mangstring.SelectMany(s => s.Split(' '));
            foreach(string chuoi in option2)
            {
                Console.WriteLine(chuoi);
            }

        }
        // HOW to get the index position of the result 
        public static void ex11()
        {
            var q = callogs.GroupB
        }
        #endregion

        static void Main(string[] args)
        {
            //ex1();
            //ex2();
            //ex3();
            //ex4();
            //ex5();
            //ex6();
            //ex7();
            //ex8();
            //ex9();
            ex10();
        }
    }
}
